// @Author EthanScriptOn
// @Date 2023/11/29 17:48:00
// @Desc
package actuator

import (
	"fmt"
	"gitee.com/fatzeng/srf_switch_basic_components/util"
	"gitee.com/fatzeng/srf_switch_stream_bridge/bridge"
	"gitee.com/fatzeng/srf_switch_stream_bridge/framework/holder"
	"sync"
)

type Stage string

const (
	ParameterCollection   Stage = "Parameter_Collection"
	ParameterConstruction Stage = "Parameter_Construction"
	OperatorExecute       Stage = "Operator_Execute"
	ResultAnalysis        Stage = "Result_Analysis"
	ResultCollection      Stage = "Result_Collection"
)

type SrfSwitchBridgeActuatorContext struct {
	BridgeConfig     *bridge.BridgeConfig
	operatorResponse map[interface{}]interface{}
	mu               sync.RWMutex
	recordHolder     *holder.RecordHolder
}

type SrfSwitchActuatorContext struct {
	groupConfig        *bridge.GroupConfig
	isAsync            bool
	stateTimeUnit      holder.ExecuteTimeUnit
	operatorContextMap map[interface{}]*SrfSwitchBridgeActuatorContext
}

func GenerateSrfSwitchActuatorContext(groupConfig *bridge.GroupConfig, stateTimeUnit holder.ExecuteTimeUnit, isAsync bool) *SrfSwitchActuatorContext {
	return &SrfSwitchActuatorContext{groupConfig: groupConfig, isAsync: isAsync, stateTimeUnit: stateTimeUnit, operatorContextMap: make(map[interface{}]*SrfSwitchBridgeActuatorContext)}
}

func GenerateSrfSwitchBridgeActuatorContext(bridgeConfig *bridge.BridgeConfig, recordHolder *holder.RecordHolder) *SrfSwitchBridgeActuatorContext {
	return &SrfSwitchBridgeActuatorContext{BridgeConfig: bridgeConfig, operatorResponse: make(map[interface{}]interface{}), mu: sync.RWMutex{}, recordHolder: recordHolder}
}

func (s *SrfSwitchBridgeActuatorContext) GetRecordHolder() *holder.RecordHolder {
	return s.recordHolder
}

func (s *SrfSwitchBridgeActuatorContext) Record(stage Stage, recordLog string) (err error) {
	recordHolder := s.GetRecordHolder()
	if recordHolder == nil {
		return fmt.Errorf("record holder is nil")
	}
	logHolder := recordHolder.LogHolder
	if logHolder != nil {
		return fmt.Errorf("log holder is nil")
	}
	logHolder.LogRecord(fmt.Sprintf("stage: %s, record log: %s", stage, recordLog))
	return
}

func (s *SrfSwitchBridgeActuatorContext) SaveResponse(operatorIdentifier interface{}, response interface{}) {
	_ = util.LockWithSync(s.mu.Lock, s.mu.Unlock, func() (err error) {
		s.operatorResponse[operatorIdentifier] = response
		return
	})
}

func (s *SrfSwitchBridgeActuatorContext) GetResponse(operatorIdentifier interface{}) (response interface{}, hasResponse bool) {
	_ = util.LockWithSync(s.mu.Lock, s.mu.Unlock, func() (err error) {
		response, hasResponse = s.operatorResponse[operatorIdentifier]
		return
	})
	return
}

func (s *SrfSwitchActuatorContext) GetResponse(bridgeIdentifier interface{}) (response interface{}, hasResponse bool) {
	context, ok := s.operatorContextMap[bridgeIdentifier]
	if !ok {
		return nil, false
	}
	return context.GetResponse(context.BridgeConfig.MultiChannelDataOperatorIdentifier)
}

func (s *SrfSwitchActuatorContext) GetAdaptationBridgeConfig(bridgeIdentifier interface{}) (response []*bridge.BridgeConfig, hasResponse bool) {
	for _, config := range s.groupConfig.BridgeConfigs {
		if config.BridgeIdentifier == bridgeIdentifier {
			response = append(response, config)
		}
	}
	return response, len(response) != 0
}

func (s *SrfSwitchActuatorContext) ShallowClone() *SrfSwitchActuatorContext {
	return &SrfSwitchActuatorContext{
		groupConfig:        s.groupConfig,
		isAsync:            s.isAsync,
		stateTimeUnit:      s.stateTimeUnit,
		operatorContextMap: s.operatorContextMap,
	}
}

func (s *SrfSwitchActuatorContext) GetGroupConfig() *bridge.GroupConfig {
	return s.groupConfig
}

func (s *SrfSwitchActuatorContext) SetGroupConfig(config *bridge.GroupConfig) {
	s.groupConfig = config
}

func (s *SrfSwitchActuatorContext) GetAsync() bool {
	return s.isAsync
}

func (s *SrfSwitchActuatorContext) SetAsync(async bool) {
	s.isAsync = async
}

func (s *SrfSwitchActuatorContext) GetStateTimeUnit() holder.ExecuteTimeUnit {
	return s.stateTimeUnit
}

func (s *SrfSwitchActuatorContext) SetStateTimeUnit(unit holder.ExecuteTimeUnit) {
	s.stateTimeUnit = unit
}

func (s *SrfSwitchActuatorContext) GetOperatorContextMap() map[interface{}]*SrfSwitchBridgeActuatorContext {
	return s.operatorContextMap
}

func (s *SrfSwitchActuatorContext) SetOperatorContextMap(operatorContextMap map[interface{}]*SrfSwitchBridgeActuatorContext) {
	s.operatorContextMap = operatorContextMap
}
